using XjjXmm.Infrastructure.Exceptions;
using XjjXmm.Infrastructure.Mapper;
using xjjxmm.infrastructure.repository.entity;
using xjjxmm.infrastructure.repository.interfaces;
using XjjXmm.Infrastructure.ToolKit;
using xjjxmm.infrastructure.ToolKit.IdKit;

namespace xjjxmm.infrastructure.service.crud;

public class CrudService<TModel, TEntity> : CrudService<TModel, TModel, TEntity>,
	ICrudService<TModel>
	where TEntity : class, new()
{
	public CrudService(IRepository<TEntity> Repository) : base(Repository)
	{
	}
}
	
public class CrudService<TSaveModel, TDetailModel, TEntity> 
	: CrudService<TSaveModel, TSaveModel, TDetailModel, TEntity>, ICrudService<TSaveModel, TDetailModel>
	where TEntity : class, new()
{
	public CrudService(IRepository<TEntity> Repository) : base(Repository)
	{
	}

	public virtual async Task<bool> Save(TSaveModel input)
	{
		var entity = input.MapTo<TSaveModel, TEntity>();

		switch (entity)
		{
			case null:
				return false;
			case EntityFull full when full.Id.IsNullOrEmpty():
			{
				var res =  await base.Add(input);
				return res;
			}
			case EntityFull full:
				return await base.Update(input);
			case EntityAdd tmp when tmp.Id.IsNullOrEmpty():
			{
				var res = await base.Add(input);
				
				return res;
			}
			case EntityAdd tmp:
				return await base.Update(input);
			default:
			{
				var id = entity.GetFieldValue("Id");

				if (id == null || string.IsNullOrEmpty(id.ToString()))
				{
					var res =  await base.Add(input);
					return res;
				}
				else
				{
					return await base.Update(input);

				}
			}
		}

		//throw ExceptionFactory.Create(BussinessStatusCodes.Status999Falid, "实体层没有继承entityful/entityAdd");
	}
}
	
public class CrudService<TAddModel, TUpdateModel, TDetailModel, TEntity> : BaseService, ICrudService<TAddModel, TUpdateModel, TDetailModel> 
	where TEntity : class, new()
{
	private readonly IRepository<TEntity> _Repository;
       
	/// <summary>
	/// 映射
	/// </summary>
	// public IMapper _mapper;
	public CrudService(IRepository<TEntity> Repository)
	{
		_Repository = Repository;
	}

	protected TEntity GetAddEntity(TAddModel model)
	{
		var entity = model.MapTo<TAddModel, TEntity>();
		FillAdd(entity!);
		return entity!;
	}
        
	protected List<TEntity> GetAddEntity(List<TAddModel> model)
	{
		var entity = model.MapTo<TAddModel, TEntity>()!.ToList();
		FillAdd(entity);

		return entity;
	}
        
	protected TEntity GetUpdateEntity(TUpdateModel model)
	{
		var entity = model.MapTo<TUpdateModel, TEntity>();
		FillUpdate(entity);
		return entity!;
	}
        
	protected List<TEntity> GetUpdateEntity(List<TUpdateModel> model)
	{
		var entity = model.MapTo<TUpdateModel, TEntity>()?.ToList();
		FillUpdate(entity);

		return entity!;
	}

	public virtual async Task<bool> Add(TAddModel model)
	{
		var entity = GetAddEntity(model);
		//model.SetFieldValue("Id", entity.GetFieldValue("Id"));
		return await _Repository.Add(entity);
	}

	public virtual async Task<bool> Add(List<TAddModel> model)
	{
		var entity = GetAddEntity(model);
		return await _Repository.Add(entity);
	}

	public virtual async Task<bool> Update(TUpdateModel model)
	{
		var entity = GetUpdateEntity(model);
		return await _Repository.Update(entity);
	}
	
	public virtual async Task<bool> Update(List<TUpdateModel> model)
	{
		var entity = GetUpdateEntity(model);
		return await _Repository.Update(entity);
	}
        
	public virtual async Task<bool> Delete(string id)
	{
		return await _Repository.Delete(id);
	}

	public virtual async Task<bool> SoftDelete(string id)
	{
		return await _Repository.SoftDelete(id);
	}

	public virtual async Task<bool> SoftDelete(string[] id)
	{
		return await _Repository.SoftDelete(id);
	}

	public virtual async Task<bool> Restore(string id)
	{
		return await _Repository.Restore(id);
	}
	
	public virtual async Task<TDetailModel> Find(string id)
	{
		var entity = await _Repository.Find(id);
		return entity.MapTo<TEntity, TDetailModel>()!;
	}

	public virtual async Task<IEnumerable<TDetailModel>> GetAll()
	{
		var entities = await _Repository.GetAll();

		var res = entities.MapTo<TEntity, TDetailModel>();
		return res!;
	}
	
	protected void FillAdd(TEntity entity)
	{
		switch (entity)
		{
			case EntityFull full:
			{
				var tmp = full;
				tmp!.CreatedTime = DateTime.Now;
				tmp.CreatorName = UserContext?.NickName;
				tmp.CreatorId = UserContext?.Id;

				tmp.UpdateTime = DateTime.Now;
				tmp.UpdaterId = UserContext?.Id;
				tmp.UpdaterName = UserContext?.NickName;

				tmp.TimeStamp = DateTime.Now.ToTotalMilliseconds();

				if (string.IsNullOrEmpty(tmp.Id))
				{
					tmp.Id = SnowFlakeKit.NextId().ToString();
				}

				break;
			}
			case EntityAdd add:
			{
				var tmp = add;
				tmp!.CreatedTime = DateTime.Now;
				tmp.CreatorName = UserContext?.NickName;
				tmp.CreatorId = UserContext?.Id;

				if (string.IsNullOrEmpty(tmp.Id))
				{
					tmp.Id = SnowFlakeKit.NextId().ToString();
				}

				break;
			}
			default:
			{
				var id = entity.GetFieldValue("Id");

				if (id == null || string.IsNullOrEmpty(id.ToString()))
				{
					entity.SetFieldValue("Id", SnowFlakeKit.NextId().ToString());
				}

				entity.SetFieldValue("CreatedTime", DateTime.Now);
				entity.SetFieldValue("CreatorName", UserContext?.NickName);
				entity.SetFieldValue("CreatorId", UserContext?.Id);

				entity.SetFieldValue("UpdateTime", DateTime.Now);
				entity.SetFieldValue("UpdaterName", UserContext?.NickName);
				entity.SetFieldValue("UpdaterId", UserContext?.Id);
				break;
			}
		}
	}

	protected void FillAdd(List<TEntity> entities)
	{
		entities.ForEach(e => FillAdd(e));
	}
	protected void FillUpdate(TEntity? entity)
	{
		if (entity == null) return;

		if (entity is EntityFull)
		{
			var tmp = entity as EntityFull;

			tmp!.UpdateTime = DateTime.Now;
			tmp.UpdaterId = UserContext?.Id;
			tmp.UpdaterName = UserContext?.NickName;
			tmp.TimeStamp = DateTime.Now.ToTotalMilliseconds();
		}
		else
		{
           
            entity.SetFieldValue("UpdateTime", DateTime.Now);
            entity.SetFieldValue("UpdaterName", UserContext?.NickName);
            entity.SetFieldValue("UpdaterId", UserContext?.Id);
        }
	}

	protected void FillUpdate(List<TEntity>? entities)
	{
		entities?.ForEach(e => FillUpdate(e));
	}
}
